{
	UCE - cross-platform game engine written in delphi.
	Copyright (c) 2009, Shutko Vitaly

	This file is part of UCE.

	UCE is free software; you can redistribute it and/or
	modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 2.1 of the License, or (at your option) any later version.

	UCE is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
}

unit uTexGL;

interface

uses
  uOpenGL, uTyp, uGfx, uGfxGL, uTex;

type
  TTexGL = class(TTex)
    id: TGLuint;

    procedure Bind; override;
    procedure SetSmooth(smooth: Boolean); override;

    function Upload(w, h, format: Integer; data: TBytes; smooth: Boolean): Boolean; override;
    function Download(var data: TBytes): Boolean; override;

    constructor Create;
    destructor Destroy; override;
  end;

implementation

uses
  uVar;

function FormatToGL(format: Integer): Cardinal;
begin
  case format of
    TEX_RGBA: Result := GL_RGBA;
    TEX_RGB: Result := GL_RGB;
    TEX_ALPHA: Result := GL_ALPHA;
    else Result := 0;
  end;
end;

constructor TTexGL.Create;
begin
  id := 0;
end;

destructor TTexGL.Destroy;
begin
  if id <> 0 then
    glDeleteTextures(1, @id);
end;

procedure TTexGL.Bind;
begin
  glBindTexture(GL_TEXTURE_2D, id);
end;

procedure TTexGL.SetSmooth(smooth: Boolean);
begin
  glBindTexture(GL_TEXTURE_2D, id);

  if smooth then
  begin
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  end else
  begin
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  end;

  Self.smooth := smooth;
end;

procedure SwapRGB(data: TBytes; w, h, format: Integer);
var
  i, j, comps: Integer;
  temp: Byte;
begin
  if (format = TEX_RGBA) or (format = TEX_RGB) then
  begin
    comps := FormatToBPP(format) div 8;

    for j := 0 to h - 1 do
      for i := 0 to  w - 1 do
      begin
        temp := data[(j * w + i) * comps];
        data[(j * w + i) * comps] := data[(j * w + i) * comps + 2];
        data[(j * w + i) * comps + 2] := temp;
      end;
  end;
end;
  
function TTexGL.Upload(w, h, format: Integer; data: TBytes; smooth: Boolean): Boolean;
begin
  Result := False;

  SwapRGB(data, w, h, format);

  glGenTextures(1, @id);
  glBindTexture(GL_TEXTURE_2D, id);

  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

  if(TGfxGL(gfx).exts.texBorderClamp) then
  begin
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER_SGIS);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER_SGIS);
  end else
  begin
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  end;

  if smooth then
  begin
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  end else
  begin
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  end;

  glTexImage2D(GL_TEXTURE_2D, 0, FormatToGL(format), w, h, 0,
    FormatToGL(format), GL_UNSIGNED_BYTE, data);

  Result := True;
end;

function TTexGL.Download(var data: TBytes): Boolean;
begin
  Result := False;

  if id = 0 then
  begin
    //error
    Exit;
  end;

  SetLength(data, w * h * FormatToBPP(format) div 8);

  glBindTexture(GL_TEXTURE_2D, id);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  glGetTexImage(GL_TEXTURE_2D, 0, FormatToGL(format), GL_UNSIGNED_BYTE, @data[0]);

  SwapRGB(data, w, h, format);
  FlipV(data, w, h, format);

  Result := True;
end;

end.
